#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
 
#include <linux/input.h>
#include <linux/uinput.h>
 
void mouse_move(int fd, int dx, int dy)
{
	struct input_event ev;
 
	memset(&ev, 0, sizeof(struct input_event));
	ev.type = EV_REL;
	ev.code = REL_X;
	ev.value = dx;
	if (write(fd, &ev, sizeof(struct input_event)) < 0) {
		printf("move error\n");
	}
 
	memset(&ev, 0, sizeof(struct input_event));
	ev.type = EV_REL;
	ev.code = REL_Y;
	ev.value = dy;
	if (write(fd, &ev, sizeof(struct input_event)) < 0) {
		printf("move error\n");
	}
 
	
	memset(&ev, 0, sizeof(struct input_event));
	ev.type = EV_SYN;
	ev.code = SYN_REPORT;
	ev.value = 0;
	if (write(fd, &ev, sizeof(struct input_event)) < 0) {
		printf("move error\n");
	}
}
 
void mouse_report_key(int fd, uint16_t type, uint16_t keycode, int32_t value)
{
	struct input_event ev;
 
	memset(&ev, 0, sizeof(struct input_event));
 
	ev.type = type;
	ev.code = keycode;
	ev.value = value;
 
	if (write(fd, &ev, sizeof(struct input_event)) < 0) {
		printf("key report error\n");
	}
}

int create_input_dev(void)
{
	struct uinput_user_dev mouse;
	int fd, ret;
 
	fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
	if (fd < 0) {
		return fd;
	}
 
	ioctl(fd, UI_SET_EVBIT, EV_SYN);
 
	ioctl(fd, UI_SET_EVBIT, EV_KEY);
	ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
	ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
	ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE);
 
	ioctl(fd, UI_SET_EVBIT, EV_REL);
	ioctl(fd, UI_SET_RELBIT, REL_X);
	ioctl(fd, UI_SET_RELBIT, REL_Y);
 
	/*ioctl(fd, UI_SET_EVBIT, EV_ABS);
	ioctl(fd, UI_SET_ABSBIT, ABS_X);
	ioctl(fd, UI_SET_ABSBIT, ABS_Y);
	ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE);*/
 
	memset(&mouse, 0, sizeof(struct uinput_user_dev));
	snprintf(mouse.name, UINPUT_MAX_NAME_SIZE, "mouse");
	mouse.id.bustype = BUS_USB;
	mouse.id.vendor = 0x1234;
	mouse.id.product = 0xfedc;
	mouse.id.version = 1;
 
	/*mouse.absmin[ABS_X] = 0;
	mouse.absmax[ABS_X] = 1023;
	mouse.absfuzz[ABS_X] = 0;
	mouse.absflat[ABS_X] = 0;
	mouse.absmin[ABS_Y] = 0;
	mouse.absmax[ABS_Y] = 767;
	mouse.absfuzz[ABS_Y] = 0;
	mouse.absflat[ABS_Y] = 0;*/
 
	ret = write(fd, &mouse, sizeof(struct uinput_user_dev));
 
	ret = ioctl(fd, UI_DEV_CREATE);
	if (ret < 0) {
		close(fd);
		return ret;
	}
	sleep(1);
	return fd;
}

void close_dev(int fd)
{
	ioctl(fd, UI_DEV_DESTROY);
	close(fd);
}

void mouse_button_right(int fd)
{
	mouse_report_key(fd, EV_KEY, BTN_RIGHT, 1);
	mouse_report_key(fd, EV_SYN, SYN_REPORT, 0);
	mouse_report_key(fd, EV_KEY, BTN_RIGHT, 0);
	mouse_report_key(fd, EV_SYN, SYN_REPORT, 0);
}

int main(void)
{
	int fd = create_input_dev();
	mouse_button_right(fd);
	close_dev(fd);
	return 0;
}
